﻿using System;
#if WINDOWS_PHONE
using System.Net;
#else
using System.Web;
#endif


using Newtonsoft.Json;


namespace Tulde.Core
{
    /// <summary>
    /// A JSON ViewModel object serializer.  This Serializer relies upon NewtonSofts JSON serializer.  All view models
    /// must be appropriately annotated with Newtonsoft specific Attributes to participate in the JSON Serialization process.
    /// </summary>
    public class JSONViewModelSerializer : IViewModelSerializer
    {

        #region IViewModelSerializer Members
        /// <summary>
        /// Serializes the supplied object instance as a JSON String.
        /// throws ArgumentNullExpcetion.
        /// </summary>
        /// <param name="instance">a view model object instance</param>
        /// <example>ArgumentNullException</example>
        /// <returns>a json serialized string</returns>
        public string Serialize(object instance)
        {
            Guard.IsNotNull(instance);
            return JsonConvert.SerializeObject(instance);
        }
        /// <summary>
        /// Deserializes a json string as a generic view model type T
        /// throw ArgumentNullException
        /// </summary>
        /// <typeparam name="T">The type to deserialize</typeparam>
        /// <param name="serializedInstance">a valid json string</param>
        /// <example>ArgumentNullException</example>
        /// <returns></returns>
        public T Deserialize<T>(string serializedInstance)
        {
            Guard.IsNotNull(serializedInstance);
            try
            {
                return JsonConvert.DeserializeObject<T>(serializedInstance);
            }
            catch (Exception ex)
            {
                return Activator.CreateInstance<T>();
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="type"></param>
        /// <param name="serializedInstance"></param>
        /// <returns></returns>
        public object Deserialize(Type type, string serializedInstance)
        {
            Guard.IsNotNull(serializedInstance);
            try
            {
                return JsonConvert.DeserializeObject(serializedInstance, type);
            }
            catch
            {
                return Activator.CreateInstance(type);
            }
        }
        /// <summary>
        /// A utility method to serialize a viewmodel to a url query string parameter.  The url parameter name is derived from the full
        /// type of the viewmodel instance with each "." replaced by "_".
        /// </summary>
        /// <param name="instance"></param>
        /// <returns></returns>
        public string SerializeToUrlParameter(object instance)
        {
            Guard.IsNotNull(instance);
            Type t = instance.GetType();
            string urlParameter = t.FullName.Replace(".", "_");
            return String.Format("{0}={1}", urlParameter, HttpUtility.UrlEncode(Serialize(instance)));
        }
        /// <summary>
        /// Reads a key/value pair from the supplied IDictionary instance and attempts to deserialize the value into Type T.
        /// 
        /// The key is derived from the full type of (T)  with each "." replaced by "_".
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="queryStringParameters"></param>
        /// <returns></returns>
        public T DeserializeFromUrlParameter<T>(System.Collections.Generic.IDictionary<string, string> queryStringParameters)
        {
            Guard.IsNotNull(queryStringParameters);
            Type t = typeof(T);
            string urlParameter = t.FullName.Replace(".", "_");
            if (queryStringParameters.ContainsKey(urlParameter))
            {
                return this.Deserialize<T>(HttpUtility.UrlDecode(queryStringParameters[urlParameter]));
            }
            else
            {
                return default(T);
            }
        }


        #endregion
    }
}
